Skip to content

curation tabs change#1933

Merged
ragnep merged 4 commits intomainfrom
curation-wave-tabs
Feb 16, 2026
Merged

curation tabs change#1933
ragnep merged 4 commits intomainfrom
curation-wave-tabs

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Feb 16, 2026

Summary by CodeRabbit

  • New Features

    • Responsive curation group UI: desktop shows horizontal tabs; mobile shows a dropdown with selectable items and avatars.
  • Bug Fixes / Improvements

    • Sort control simplified to a single dropdown for consistent behavior and faster rendering.
    • Header layout reorganized for improved spacing and clarity.
  • Style

    • Updated dropdown button and icon styling for improved visual consistency.
  • Tests

    • Tests updated to cover desktop tabs and mobile dropdown interactions.

Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 16, 2026

📝 Walkthrough

Walkthrough

Refactors leaderboard header: consolidates sorting UI to a single CommonDropdown, adds breakpoint-aware rendering in curation group select (mobile CommonDropdown vs desktop tabs) with per-group parallel queries, adjusts CommonDropdown styling, and updates tests/mocks to match these behaviors.

Changes

Cohort / File(s) Summary
Sort UI & tests
components/waves/leaderboard/header/WaveleaderboardSort.tsx, __tests__/components/waves/leaderboard/header/WaveleaderboardSort.test.tsx
Removed prefetch/breakpoint logic and waveId/curatedByGroupId props; always renders a small CommonDropdown. Tests updated to assert dropdown rendering, CommonDropdown props, and onSortChange interactions.
Curation group select & tests
components/waves/leaderboard/header/WaveLeaderboardCurationGroupSelect.tsx, __tests__/components/waves/leaderboard/header/WaveLeaderboardCurationGroupSelect.test.tsx
Introduced responsive rendering: mobile uses CommonDropdown, desktop uses inline tabs. Replaced single fetch with per-group useQueries, added avatar mapping, and updated tests with breakpoint-aware mocks and mobile dropdown item interactions.
Header layout
components/waves/leaderboard/header/WaveleaderboardHeader.tsx
Rearranged WaveleaderboardSort placement and adjusted Drop button wrapper/class application; layout context changed but component signatures unchanged.
CommonDropdown styling
components/utils/select/dropdown/CommonDropdown.tsx
Adjusted padding/text sizes, reduced trailing padding, changed caret icon sizing, and added filterLabel color class (visual/styling tweaks).
Tests/mocks
__tests__/components/waves/leaderboard/header/...
Replaced CommonSelect mock with breakpoint-aware approach, introduced a CommonDropdown mock for mobile, mocked react-query useQueries returns, and reset breakpoint state between tests.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WaveCuration as WaveLeaderboardCurationGroupSelect
    participant QueryLayer as useQueries
    participant Dropdown as CommonDropdown
    participant Parent as ParentHandler

    User->>WaveCuration: render (viewport check)
    WaveCuration->>QueryLayer: fetch per-group details (parallel)
    QueryLayer-->>WaveCuration: group details (avatars)
    alt mobile
        WaveCuration->>Dropdown: render mobile dropdown with items
        User->>Dropdown: click item
        Dropdown-->>WaveCuration: onChange(value)
        WaveCuration->>Parent: propagate selection
    else desktop
        WaveCuration->>WaveCuration: render inline tab buttons
        User->>WaveCuration: click tab
        WaveCuration->>Parent: propagate selection
    end
Loading
sequenceDiagram
    participant User
    participant WaveSort as WaveleaderboardSort
    participant Dropdown as CommonDropdown
    participant Parent as ParentHandler

    User->>WaveSort: view component
    WaveSort->>Dropdown: render sort items
    User->>Dropdown: open & select sort
    Dropdown-->>WaveSort: onChange(sort)
    WaveSort->>Parent: onSortChange(sort)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • #1930: Modifies WaveleaderboardSort and related tests with breakpoint-driven dropdown vs tab rendering—closely related to this refactor.
  • #1739: Changes WaveleaderboardSort UI/logic; overlaps with consolidation to a single dropdown.
  • #1649: Updates CommonDropdown implementation/styling; directly related to styling changes applied here.

Suggested reviewers

  • prxt6529
  • simo6529

Poem

🐰
Hopping through props and dropdown light,
Tabs that stretch and mobiles that bite,
Avatars fetched in parallel run,
Click a choice — the sort is done.
A tiny refactor, tidy and bright.

🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'curation tabs change' is vague and generic, using non-descriptive terms that don't convey meaningful information about the changeset's main objectives. Consider using a more descriptive title that specifies the key change, such as 'Make WaveLeaderboardCurationGroupSelect responsive with mobile dropdown' or 'Simplify WaveleaderboardSort to single dropdown UI'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch curation-wave-tabs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
components/waves/leaderboard/header/WaveLeaderboardCurationGroupSelect.tsx (2)

86-123: Desktop tabs lack semantic role and aria attributes.

The view mode tabs in WaveleaderboardHeader.tsx (Line 139-148) use role="tablist", role="tab", and aria-selected. These curation group tabs serve a similar purpose but lack equivalent accessibility attributes, creating an inconsistency.

♿ Suggested accessibility improvement
   return (
     <div
       data-testid="curation-group-select"
-      className="tw-flex tw-items-center tw-gap-x-1"
+      className="tw-flex tw-items-center tw-gap-x-1"
+      role="tablist"
+      aria-label="Curation groups"
     >
       {items.map((item) => {
         const pfp = item.value ? pfpMap.get(item.value) : null;
         return (
           <button
             key={item.key}
             type="button"
+            role="tab"
+            aria-selected={selectedGroupId === item.value}
             className={getTabClassName(item.value)}
             onClick={() => onChange(item.value)}
           >

43-53: Spreading query results into useMemo deps is fragile.

The // eslint-disable-next-line react-hooks/exhaustive-deps suppression on the spread ...groupDetailsQueries.map((q) => q.data) works in practice because react-query preserves referential identity for unchanged data, but the deps array length changes if groups changes, which can confuse the hooks contract. Consider deriving a stable dependency instead.

♻️ Alternative: use a JSON-serialized key
   const pfpMap = useMemo(() => {
     const map = new Map<string, string>();
     groups.forEach((group, i) => {
       const pfp = groupDetailsQueries[i]?.data?.created_by?.pfp;
       if (pfp) {
         map.set(group.id, pfp);
       }
     });
     return map;
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [groups, ...groupDetailsQueries.map((q) => q.data)]);
+  }, [groups, groupDetailsQueries]);

Since useQueries returns a new array reference only when query results change, using the array directly is equivalent and avoids the lint suppression. Alternatively, if you want more precise control, you could extract a serialized key from the query data.

Signed-off-by: ragnep <ragneinfo@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@components/waves/leaderboard/header/WaveLeaderboardCurationGroupSelect.tsx`:
- Line 21: The hydration mismatch comes from createBreakpoint initializing
differently on server vs client; fix by client-only rendering: change the export
of WaveLeaderboardCurationGroupSelect to use Next's dynamic import with ssr:
false (i.e., export default dynamic(() =>
import('./WaveLeaderboardCurationGroupSelect'), { ssr: false })), remove or keep
createBreakpoint usage only for client, and ensure any breakpoint-dependent
rendering (CommonDropdown vs tab buttons) happens only in the client-only
component so server and client markup match.
- Around line 43-53: The current WaveLeaderboardCurationGroupSelect creates
pfpMap with a variable-length dependency array ([groups,
...groupDetailsQueries.map(q=>q.data)]) which triggers React warnings and is
suppressed by eslint-disable; instead refactor to produce a single stable
dependency (e.g., use useQueries' combine to return { data:
results.map(r=>r.data?.created_by?.pfp) } or compute a stable
key/hash/JSON.stringify of the data) and then compute pfpMap in useMemo
depending only on [groups, groupData] (or [groups, stableKey]); remove the
eslint-disable and the spread dependency, and reference the pfpMap computation
and the groupDetailsQueries/useQueries call in
WaveLeaderboardCurationGroupSelect when applying the fix.
🧹 Nitpick comments (1)
components/waves/leaderboard/header/WaveLeaderboardCurationGroupSelect.tsx (1)

86-125: Desktop tab rendering is well-structured.

Good details: type="button" prevents accidental form submissions, alt="" is correct for decorative avatars, and the conditional pfp rendering gracefully handles the loading state (no avatar until data arrives).

One optional nit: getTabClassName is re-created on every render. Since it captures selectedGroupId from closure, you could extract it to a useCallback or pass selectedGroupId as a parameter to a module-level function. This is purely a minor optimization and not necessary given the component's complexity.

Comment thread components/waves/leaderboard/header/WaveLeaderboardCurationGroupSelect.tsx Outdated
Signed-off-by: ragnep <ragneinfo@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

@ragnep ragnep merged commit f34d7d9 into main Feb 16, 2026
6 checks passed
@ragnep ragnep deleted the curation-wave-tabs branch February 16, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants